/*
 * Licensed to the 南京汇海交通科技有限公司
 *
 * Copyright (c) 2025.
 * All rights reserved.
 *
 * 本软件属南京汇海交通科技有限公司所有，在未获得南京汇海交通科技有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.chframework.boot.web.autoconfigure;

import com.chframework.boot.web.support.BaseUrlBuilder;
import com.chframework.common.constant.ApplicationConstant;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.License;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springdoc.webmvc.core.configuration.SpringDocWebMvcConfiguration;
import com.chframework.boot.core.properties.Swagger3Property;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.core.type.AnnotatedTypeMetadata;

import org.springdoc.core.utils.Constants;

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@Conditional(Swagger3AutoConfiguration.SwaggerEnableCondition.class)
@AutoConfigureBefore({SpringDocWebMvcConfiguration.class})
public class Swagger3AutoConfiguration {

    /**
     * 对 开发环境、测试环境放、验收环境 开放swagger-ui，若是 生产环境 则禁止访问
     */
    private static final Profiles PROFILES = Profiles.of("dev", "test", "uat"); // "prod"

    /**
     * swagger3文档配置
     */
    @Bean
    @ConfigurationProperties(prefix = "application.swagger")
    public Swagger3Property swagger3Property() {
        return new Swagger3Property();
    }

    /**
     * 访问路径：http://localhost:8080/swagger-ui/index.html
     */
    @Bean
    public OpenAPI springOpenAPI(Swagger3Property swagger3Prop,
                                 ApplicationContext applicationContext) {
        // API的基本信息
        Info info = new Info()
                .title(swagger3Prop.getTitle())
                .description(swagger3Prop.getDescription())
                .version(swagger3Prop.getVersion())
                .termsOfService(getBaseUrl(applicationContext));

        if (!StringUtils.isAnyEmpty(swagger3Prop.getContactName(), swagger3Prop.getContactUrl(), swagger3Prop.getContactEmail())) {
            Contact contact = new Contact()
                    .name(swagger3Prop.getContactName())
                    .url(swagger3Prop.getContactUrl())
                    .email(swagger3Prop.getContactEmail());
            info.contact(contact);
        }

        if (!StringUtils.isAnyEmpty(swagger3Prop.getLicense(), swagger3Prop.getLicenseUrl())) {
            License license = new License()
                    .name(swagger3Prop.getLicense())
                    .url(swagger3Prop.getLicenseUrl());
            info.license(license);
        }

        // API的额外信息
        ExternalDocumentation documentation =
                new ExternalDocumentation()
                        .description(swagger3Prop.getDocDesc())
                        .url(swagger3Prop.getDocUrl());

        return new OpenAPI()
                .info(info)
                .externalDocs(documentation);
    }

    /**
     * 创建SpringWeb应用启动后的访问BaseUrl
     */
    private String getBaseUrl(ApplicationContext applicationContext) {
        if (applicationContext instanceof ServletWebServerApplicationContext) {
            return BaseUrlBuilder.createBaseUrlAboutSpringWeb(applicationContext,
                    (serverProperties) -> serverProperties.getServlet().getContextPath());
        } else {
            return ApplicationConstant.LOCAL_URL;
        }
    }

    /**
     * 判断是否启用 swagger3
     */
    public static class SwaggerEnableCondition implements Condition {
        @Override
        public boolean matches(@NotNull ConditionContext context, @NotNull AnnotatedTypeMetadata metadata) {
            Environment environment = context.getEnvironment();
            Boolean enableSwaggerUI = environment.getProperty(Constants.SPRINGDOC_ENABLED, Boolean.class, false);
            return environment.acceptsProfiles(PROFILES) && enableSwaggerUI;
        }
    }

}
